﻿/* 
   Copyright 2011 LUCA Studios LLC & John Evans

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

namespace LUCAStudios.Silverlight.Controls
{
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Markup;
    using System.Linq;

    /// <summary>
    /// Provides a base Layout container for LUCASoft Liquid controls
    /// </summary>
    //[StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(LUCATabWindow))]

    [ContentProperty("Children")]
    public sealed class LUCALayoutPanel : ContainerBase
    {
        private static readonly HashSet<ControlBase> PersistentRegistry = new HashSet<ControlBase>();
        
        /// <summary>
        /// Constructor
        /// </summary>
        public LUCALayoutPanel()
        {
            DefaultStyleKey = typeof(LUCALayoutPanel);
            LayoutUpdated += LUCALayoutPanelLayoutUpdated;
        }

        void LUCALayoutPanelLayoutUpdated(object sender, EventArgs e)
        {
            LayoutUpdated -= LUCALayoutPanelLayoutUpdated;
            InitWindowManipulatorService();
        }

        /// <summary>
        /// Use to register and access controls that need to remain persistant even after being removed from the visual tree.
        /// Typically this is used for windows that need to toggle at user discretion
        /// </summary>
        public static HashSet<ControlBase> PersistentControlRegistry
        {
            get { return PersistentRegistry; }
        }

        #region private

        internal Panel RootVisual { get; private set; }
        internal LUCAWindowManipulator WindowManipulator { get; private set; }

        private void InitWindowManipulatorService()
        {
            if (WindowManipulator != default(LUCAWindowManipulator)) return;

            RootVisual = Application.Current.RootVisual.FindElement<Panel>();// this.FindElement<Grid>("RootPanel");

            if (RootVisual == default(Panel))
            {
                RootVisual = this.FindParentByType<Panel>();
            }

            if (RootVisual == default(Panel))
                throw new Exception("rootVisual not found");

            WindowManipulator = new LUCAWindowManipulator(RootVisual);
        }
        
#if DEBUG
        public void SetDropTargetVisibility(Visibility visibility)
        {
            WindowManipulator.ShowDropTargets = visibility == Visibility.Visible;
        }

        //output a visual representation of the layout heirarchy to the logger

        internal void DebugTree(string header, bool clear)
        {
            if (clear) Logger.Clear();
            Logger.AddEntry(string.Empty, String.Format("Tree Dump: {0}", header));
            DebugTreeInternal(string.Empty, this);
            Logger.AddEntry(string.Empty, string.Empty);
        }

        private static void DebugTreeInternal(string prefix, ControlBase control)
        {
            Logger.AddEntry(
                string.Empty, 
                String.Format("{0} (Parent: {1}) (Children: {2})"
                    , prefix + control.GetType().Name
                    , control.ContainerContext != null ? control.ContainerContext.GetType().Name : "undefined"
                    , control is ContainerBase ? ((ContainerBase)control).Children.Count : 0)
            );

            if (control is ContainerBase && ((ContainerBase)control).Children.Count > 0)
            {
                foreach (var c in ((ContainerBase)control).Children)
                    DebugTreeInternal(String.Format("{0}......", prefix), c);
            }
        }
#endif

        /// <summary>
        /// Called when the Children collection changes
        /// </summary>
        /// <param name="e"></param>
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
                foreach (var i in e.OldItems)
                {
                    //((LiquidContainerBase)i).Level = 0;
                    //((LiquidContainerBase)i).ZOrder = 0;
                    var li = (i as WindowBase);
                    if (li == null) continue;

                    WindowManipulator.UnregisterWindow(li);
                }

            if (e.NewItems != null)
            {
                if (e.NewItems.OfType<LUCAMenuStrip>().Any())
                    throw new LUCAControlException("LUCAMenuStrip cannot be part of the main content collection.  Add it in the LUCALayoutPanel.LUCAMenuStrip property.");
            }

            base.OnCollectionChanged(e);
        }

        #endregion

        #region dependency properties

        /// <summary>
        /// Backing property for the LUCAMenuStripContext Dependency Property
        /// </summary>
        public static readonly DependencyProperty LUCAMenuStripContextProperty =
    DependencyProperty.Register("LUCAMenuStripContext", typeof(LUCAMenuStrip), typeof(LUCALayoutPanel), new PropertyMetadata(default(LUCAMenuStrip)));

        /// <summary>
        /// Dependency property which allows assignment of a LUCAMenuStrip control to the LUCALayoutPanel.
        /// The LUCALayoutPanel control will adjust the UI to accomodate for the menu control if assigned.
        /// </summary>
        public LUCAMenuStrip LUCAMenuStripContext
        {
            get { return (LUCAMenuStrip)GetValue(LUCAMenuStripContextProperty); }
            set { SetValue(LUCAMenuStripContextProperty, value); }
        }

        /// <summary>
        /// Backing property for the LiquidThemeUri Dependency Property
        /// This property is currently NOT supported by the control
        /// </summary>
        public static readonly DependencyProperty LiquidThemeUriProperty =
            DependencyProperty.Register("LiquidThemeUri", typeof (Uri), typeof (LUCALayoutPanel), new PropertyMetadata(default(Uri)));

        /// <summary>
        /// Dependency property which assigns a Theme to the LiquidLayoutPanel
        /// This property is currently NOT supported in the control
        /// </summary>
        public Uri LiquidThemeUri
        {
            get { return (Uri) GetValue(LiquidThemeUriProperty); }
            set { SetValue(LiquidThemeUriProperty, value); }
        }

        /// <summary>
        /// Backing property for the AllowDocking Dependency Property
        /// </summary>
        public static readonly DependencyProperty AllowDockingProperty =
            DependencyProperty.Register("AllowDocking", typeof (bool), typeof (LUCALayoutPanel), new PropertyMetadata(true));

        /// <summary>
        /// Dependency property which identifies if the LUCALayoutPanel allows docking at it's root borders
        /// (usually the edges of the display)
        /// </summary>
        public bool AllowDocking
        {
            get { return (bool) GetValue(AllowDockingProperty); }
            set { SetValue(AllowDockingProperty, value); }
        }

        #endregion
    }
}